package com.miplus.ccrm.core.service.action;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.miplus.ccrm.common.*;
import com.miplus.ccrm.core.controller.vo.action.*;
import com.miplus.ccrm.core.controller.vo.conf.WfNextStepVo;
import com.miplus.ccrm.core.mapper.ConContactMapper;
import com.miplus.ccrm.core.pojo.*;
import com.miplus.ccrm.core.mapper.FiVisitMapper;
import com.miplus.ccrm.core.service.FiWorkFlowCase;
import com.miplus.ccrm.core.service.conf.MsgAlertsService;
import com.miplus.ccrm.core.service.collect.FiTaskService;
import com.miplus.ccrm.core.service.file.FiApplyAttService;
import com.miplus.ccrm.core.service.strategy.CpCalllistService;
import com.miplus.ccrm.core.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
* @author pc
* @description 针对表【fi_visit】的数据库操作Service实现
* @createDate 2024-03-30 14:48:16
*/
@Slf4j
@Service
public class FiVisitServiceImpl extends MPJBaseServiceImpl<FiVisitMapper, FiVisit>
    implements FiVisitService {
    @Resource
    private FiTaskService fiTaskService;
    @Resource
    private CpCalllistService cpCalllistService;
    @Resource
    private FiWorkFlowCase fiWorkFlowCase;
    @Resource
    private FiApplyAttService fiApplyAttService;
    @Resource
    private MsgAlertsService msgAlertsService;
    @Resource
    private ConContactMapper conContactMapper;

    @Override
    public IPage<FiVisitResVo> visitList(JSysUser user, FiApplyReqVo paras)
    {
        String $usrid=user.getUsrid();
        String phnstar= JUsrPerm.getPermission(user,JUsrPerm.DISSTAR_PHN);
        return selectJoinListPage(new Page<>(paras.getPageNum(), paras.getPageSize()),
                FiVisitResVo.class,
                new MPJLambdaWrapper<FiVisit>()
                        .selectAs("fun_getnames('FI.VISIT.STATUS',t.status)",FiVisitResVo::getStatusdsc)
                        .selectAs("fun_getgrpname(t.applyusr)",FiVisitResVo::getApplygrpname)
                        .selectAs("fun_getnames('FI.VISIT.REASON',t.reason)",FiVisitResVo::getApplyreasondsc)
                        .selectAs("(select cl.wfid from cp_calllist cl where cl.clid=t.clid)", FiVisitResVo::getWfid)
                        .selectAs(String.format("fi_starSecu('%s','%s',t.contactphone,'%s')",$usrid,JUsrPerm.DISSTAR_PHN,phnstar),FiVisitResVo::getContactphone)
                        .leftJoin(FiCreditcases.class,"ct",FiCreditcases::getCreditcaseid,FiVisit::getFicaseid)
                        .select(FiVisit::getVisitnumber,FiVisit::getReason,FiVisit::getApplydt,FiVisit::getFicaseid,FiVisit::getApplydsc,FiVisit::getApplyusr,
                                FiVisit::getClid, FiVisit::getCanceldt,FiVisit::getCancelusr,FiVisit::getConfirmusr,
                                FiVisit::getConfirmdt,FiVisit::getConfirmdsc,FiVisit::getStatus,FiVisit::getTasknumber,
                                FiVisit::getVisitor,FiVisit::getVisitstarttime,FiVisit::getVisitendtime,FiVisit::getApplyMeetPerson,FiVisit::getScheduletime,
                                FiVisit::getContactname,FiVisit::getContactaddress,FiVisit::getContactnumber,
                                FiVisit::getRealcontactname,FiVisit::getRealvisitor,FiVisit::getRealcontactaddress,FiVisit::getRealcontactphone,
                                FiVisit::getTrueMeetPerson,FiVisit::getMddt,FiVisit::getMdusr
                        )
                        .apply("fc_hasapplyview(t.visitnumber,'SYS_VISIT',t.applyusr,{0},t.status,t.confirmusr)>0",$usrid)
                        .apply(JPubUtils.IsNotEmpty(paras.getApplygrp()),"fc_hasUsrInGroup(t.applyusr,{0})>0",paras.getApplygrp())
                        .eq(JPubUtils.IsNotEmpty(paras.getFicaseid()), FiVisit::getFicaseid,paras.getFicaseid())
                        .eq(JPubUtils.IsNotEmpty(paras.getStatus()),FiVisit::getStatus,paras.getStatus())
                        .eq(JPubUtils.IsNotEmpty(paras.getApplyusr()),FiVisit::getApplyusr,paras.getApplyusr())
                        .between(JPubUtils.IsNotEmpty(paras.getStartdt()), FiVisit::getApplydt,JPubUtils.StringToDate(paras.getStartdt()),JPubUtils.StringToDate(paras.getEnddt()))
                        .orderByAsc(FiVisit::getApplydt)
        );
    }

    @Override
    @Transactional
    public CmdResVo fiVisitAdd(String $usrid, FiVisitAddVo paras)
    {
        //status=0新建，1=审批中，2=审批通过，需要完成或取消才允许再次申请外访，同一个案件
        List<FiVisit> fiVisitList=selectJoinList(FiVisit.class,
                new MPJLambdaWrapper<FiVisit>()
                        .eq(FiVisit::getFicaseid,paras.getFicaseid())
                        .in(FiVisit::getStatus,
                                EnumConfirmStatus.New.value,
                                EnumConfirmStatus.Pending.value,
                                EnumConfirmStatus.Pass.value)
        );
        if(JPubUtils.IsNotEmpty(fiVisitList)){
            throw new ServiceException(EnumRCode.DataProcess.value, EnumRCode.DataProcess.name);
        }

        String clid=paras.getClid();
        if(JPubUtils.IsEmpty(clid)){
            //此任务是系统配置任务，不能delete
            clid="SYS_VISIT";
        }
        Integer wfid=cpCalllistService.getCalllistWfID(clid);

        String phone=paras.getContactphone();
        if(JPubUtils.IsNotEmpty(paras.getContactnumber())){
            ConContact contact=conContactMapper.selectById(paras.getContactnumber());
            phone=contact.getPhone();
        }

        //CAMPAIGN.CHANNEL=5 外访
        Integer tasknumber=fiTaskService.addTask($usrid,clid,paras.getFicaseid(),
                EnumFiChannel.Visit.value, paras.getContactnumber(),phone,null
        );

        log.info("applyAdd:clid={},ficaseid={},tasknumber={},wfid={},Contactnumber={}",
                clid,paras.getFicaseid(),tasknumber,wfid,paras.getContactnumber());

        FiVisit fi=new FiVisit();
        fi.setClid(clid);
        fi.setFicaseid(paras.getFicaseid());
        fi.setTasknumber(tasknumber);
        fi.setApplyusr($usrid);
        fi.setApplydt(new Date());
        fi.setReason(paras.getReason());
        fi.setApplydsc(paras.getApplydsc());
        fi.setVisitor(paras.getVisitor());
        fi.setContactname(paras.getContactname());
        fi.setContactnumber(paras.getContactnumber());
        fi.setContactphone(phone);
        fi.setContactaddress(paras.getContactaddress());
        fi.setScheduletime(paras.getScheduletime());
        fi.setApplyMeetPerson(paras.getApplyMeetPerson());
        fi.setStatus(EnumConfirmStatus.New.value); //0=新建
        fi.setMddt(new Date());
        fi.setMdusr($usrid);

        int ret=baseMapper.insert(fi);

        Integer visitnumber=fi.getVisitnumber();

        if(wfid>0){
            //wfid=0 表示此任务clid没有配置工作流，前台可以根据是否有wfid显示不通的审批流程或状态
            String status=fiWorkFlowCase.doCreate($usrid,wfid,fi.getVisitnumber(),tasknumber);

            fi=new FiVisit();
            fi.setVisitnumber(visitnumber);
            fi.setStatus(Integer.parseInt(status));
            baseMapper.updateById(fi);
        }

        return new CmdResVo(ret,fi.getVisitnumber().toString());
    }

    @Override
    public CmdResVo fiVisitConfirm(String $usrid, FiApplyConfirmVo paras)
    {
        String okstatus=paras.getActionid().toString();
        boolean confirmend=true;
        FiVisit fi = baseMapper.selectById(paras.getApplynumber());
        if(JPubUtils.IsNotEmpty(paras.getCaseactid())){
            //需要走工作流
            WfNextStepVo wfNextStepVo=fiWorkFlowCase.doExec($usrid,paras.getCaseactid(),
                    paras.getActionid(),paras.getWfcaseid(),paras.getConfirmdsc()
            );
            okstatus=wfNextStepVo.getStatus();

            //可能有多级审核,3=审核全部完成
            if(!JPubUtils.IsEqual(wfNextStepVo.getType(), EnumWorkFlowStep.End.value)) {
                confirmend=false;
            }
        }
        else{
            Integer wfid=cpCalllistService.getCalllistWfID(fi.getClid());
            if(wfid==null||wfid==0){//不使用工作流,这种情况下okstatus就是字典ID，直接写审核结果
                log.info("fiVisitConfirm.nouse workflow：okstatus={}",okstatus);
            }
            else{//可能配置错误或网络引起的，2024-08-29
                log.warn("fiVisitConfirm.nofind wf caseactid.");
                throw new ServiceException(EnumRCode.WfDataErr.value, EnumRCode.WfDataErr.name);
            }
        }

        int ret=0;
        if(JPubUtils.IsNotEmpty(okstatus)){

            if(JPubUtils.IsNotEmpty(fi.getTasknumber())&&confirmend) {
                fiTaskService.updateStatus(
                        fi.getTasknumber(),
                        $usrid,
                        fiWorkFlowCase.getPassStatus(okstatus)
                );
                msgAlertsService.msgAlertAdd(EnumFiChannel.Visit,
                        fi.getApplyusr(),
                        $usrid,
                        EnumUtil.ConfirmStatusName(okstatus)
                );
            }

            fi = new FiVisit();
            fi.setVisitnumber(paras.getApplynumber());
            fi.setStatus(Integer.parseInt(okstatus));
            fi.setConfirmusr($usrid);
            fi.setConfirmdt(new Date());
            fi.setConfirmdsc(paras.getConfirmdsc());
            ret=baseMapper.updateById(fi);
        }

        return new CmdResVo(ret,paras.getApplynumber().toString());
    }

    @Override
    public CmdResVo fiVisitCancel(String $usrid, FiApplyCancelVo paras)
    {
        FiVisit fi=baseMapper.selectById(paras.getApplynumber());
        if(JPubUtils.IsNotEmpty(fi.getTasknumber())){
            fiTaskService.updateStatus(fi.getTasknumber(),$usrid,"X");
        }
        else{
            log.warn("applyCancel:getTasknumber.isnull");
        }
        Integer wfid=cpCalllistService.getCalllistWfID(fi.getClid());
        if(wfid>0){//有工作流,取消
            fiWorkFlowCase.doCancel($usrid,wfid,fi.getVisitnumber());
        }

        fi = new FiVisit();
        fi.setVisitnumber(paras.getApplynumber());
        fi.setStatus(EnumConfirmStatus.Cancel.value);
        fi.setMdusr($usrid);
        fi.setMddt(new Date());

        int ret=baseMapper.updateById(fi);

        return new CmdResVo(ret,fi.getVisitnumber().toString());
    }

    @Override
    public CmdResVo fiVisitResult(String $usrid, FiVisitResultVo paras)
    {
        FiVisit fi = new FiVisit();
        fi.setVisitnumber(paras.getVisitnumber());
        fi.setStatus(EnumConfirmStatus.Finish.value); //这里可以根据isrpc处理
        fi.setRealvisitor(paras.getRealvisitor());
        fi.setRealcontactname(paras.getRealcontactname());
        fi.setRealcontactphone(paras.getRealcontactphone());
        fi.setRealcontactaddress(paras.getRealcontactaddress());
        fi.setTrueMeetPerson(paras.getTrueMeetPerson());
        fi.setVisitstarttime(paras.getVisitstarttime());
        fi.setVisitendtime(paras.getVisitendtime());
        fi.setMdusr($usrid);
        fi.setMddt(new Date());
        int ret=baseMapper.updateById(fi);

        fiApplyAttService.AddApplyFile(paras.getVisitnumber(),
                EnumFiChannel.Visit.toString().toLowerCase(),
                paras.getUploadList()
        );

        Integer tasknumber=paras.getTasknumber();
        if(paras.getTasknumber()==null){
            FiVisit fi2 = baseMapper.selectById(paras.getVisitnumber());
            tasknumber= fi2.getTasknumber();
        }
        if(tasknumber==null){
            log.warn("fiVisitResult:getTasknumber.isnull");
        }
        else {
            fiTaskService.saveTask(paras.getTasknumber(), $usrid, paras.getResult(),
                    paras.getResultdsc(), paras.getPtpstatus(),
                    paras.getPtp(), paras.getPtpdt()
            );
        }

        return new CmdResVo(ret,fi.getVisitnumber().toString());
    }

    @Override
    public FiVisitResVo getVisitInfo(Integer visitnumber)
    {
        return selectJoinOne(
                FiVisitResVo.class,
                new MPJLambdaWrapper<FiVisit>()
                        .selectAs("fun_getnames('FI.VISIT.STATUS',t.status)",FiVisitResVo::getStatusdsc)
                        .selectAs("(select g.grpname from sys_grp g where g.grpid=ct.sendtodept)",FiVisitResVo::getApplygrpname)
                        .selectAs("fun_getnames('FI.VISIT.REASON',t.reason)",FiVisitResVo::getApplyreasondsc)
                        .selectAs("(select cl.wfid from cp_calllist cl where cl.clid=t.clid)", FiStopResVo::getWfid)
                        .selectAs("(select cg.helpstr from cp_strategy cg where cg.clid=t.clid and cg.ccc=tv.result)",FiTask::getResult)
                        .selectAs("tv.resultdsc",FiTask::getResultdsc)
                        .leftJoin(FiCreditcases.class,"ct",FiCreditcases::getCreditcaseid,FiVisit::getFicaseid)
                        .leftJoin(FiTask.class,"tv",FiTask::getTasknumber,FiVisit::getTasknumber)
                        .selectAll(FiVisit.class)
                        .eq(FiVisit::getVisitnumber,visitnumber)
        );
    }

    @Override
    public FiVisitResVo getVisitInfoByTaskID(Integer tasknumber)
    {
        return selectJoinOne(
                FiVisitResVo.class,
                new MPJLambdaWrapper<FiVisit>()
                        .selectAs("fun_getnames('FI.VISIT.STATUS',t.status)",FiVisitResVo::getStatusdsc)
                        .selectAs("(select g.grpname from sys_grp g where g.grpid=ct.sendtodept)",FiVisitResVo::getApplygrpname)
                        .selectAs("fun_getnames('FI.VISIT.REASON',t.reason)",FiVisitResVo::getApplyreasondsc)
                        .selectAs("(select cl.wfid from cp_calllist cl where cl.clid=t.clid)", FiStopResVo::getWfid)
                        .selectAs("(select cg.helpstr from cp_strategy cg where cg.clid=t.clid and cg.ccc=tv.result)",FiTask::getResult)
                        .selectAs("tv.resultdsc",FiTask::getResultdsc)
                        .leftJoin(FiCreditcases.class,"ct",FiCreditcases::getCreditcaseid,FiVisit::getFicaseid)
                        .leftJoin(FiTask.class,"tv",FiTask::getTasknumber,FiVisit::getTasknumber)
                        .selectAll(FiVisit.class)
                        .eq(FiTask::getTasknumber,tasknumber)
        );
    }
}




